/**
 * @file sys.c
 * @author liqiang (liqiang@hacint.com.cn)
 * @brief 
 * @version 1.0.0
 * @date 2023-08-15
 * 
 * 
 */
#include "sys.h"
#include "HAL_Type.h"

/**
 * @brief 
 * 
 * @param plln :主PLL倍频系数(PLL倍频),取值范围:64~432.
 * @param pllm :主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
 * @param pllp :系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
 * @param pllq :USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
 * 
 * Fvco:VCO频率
 * SYSCLK:系统时钟频率
 * Fusb:USB,SDIO,RNG等的时钟频率
 * Fs:PLL输入时钟频率,可以是HSI,HSE等. 
 * 外部晶振为25M的时候,推荐值:plln=360,pllm=25,pllp=2,pllq=8.
 * Fvco=25*(360/25)=360Mhz
 * SYSCLK=360/2=180Mhz
 * Fusb=360/8=45Mhz
 */
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
    HAL_StatusTypeDef ret = HAL_OK;
    RCC_OscInitTypeDef RCC_OscInitStructure; 
    RCC_ClkInitTypeDef RCC_ClkInitStructure;
    
    __HAL_RCC_PWR_CLK_ENABLE();  
    
  /**
   * @brief 下面这个设置用来设置调压器输出电压级别，以便在器件未以最大频率工作
   * 时使性能与功耗实现平衡，此功能只有STM32F42xx和STM32F43xx器件有，
   * 
   */
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 
    
    RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE;     
    RCC_OscInitStructure.HSEState=RCC_HSE_ON;                      
    RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON; 
    RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE; 
    RCC_OscInitStructure.PLL.PLLM=pllm;  
    RCC_OscInitStructure.PLL.PLLN=plln;  
    RCC_OscInitStructure.PLL.PLLP=pllp;  
    RCC_OscInitStructure.PLL.PLLQ=pllq;  
    ret=HAL_RCC_OscConfig(&RCC_OscInitStructure); 
	
    if(ret!=HAL_OK) while(1);
    
    ret=HAL_PWREx_EnableOverDrive();  
    if(ret!=HAL_OK) while(1);
    
 
    RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; 
    RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1; 
    RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV4;  
    RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV2;  
    ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_5); 
		
    if(ret!=HAL_OK) while(1);
}

void  Plat_Clock_Init(void){

	Stm32_Clock_Init(360,25,2,8);
}

#ifdef  USE_FULL_ASSERT
 /**
  * @brief 当编译提示出错的时候此函数用来报告错误的文件和所在行
  * 
  * @param file ：指向源文件
  * @param line ：指向在文件中的行数
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
	while (1)
	{
	}
}
#endif

/**
 * @brief THUMB指令不支持汇编内联
 *          采用如下方法实现执行汇编指令WFI  
 * @return __asm 
 */
//__asm void WFI_SET(void)
//{
//	WFI;		  
//}

///**
// * @brief 关闭所有中断(但是不包括fault和NMI中断)
// * 
// * @return __asm 
// */
//__asm void INTX_DISABLE(void)
//{
//	CPSID   I
//	BX      LR	  
//}
///**
// * @brief 开启所有中断
// * 
// * @return __asm 
// */
//__asm void INTX_ENABLE(void)
//{
//	CPSIE   I
//	BX      LR  
//}
///**
// * @brief 设置栈顶地址
// * 
// * @param addr :栈顶地址
// * @return __asm 
// */
//__asm void MSR_MSP(u32 addr) 
//{
//	MSR MSP, r0 			//set Main Stack value
//	BX r14
//}


void WFI_SET(void)
{
    __asm("WFI");
}

void INTX_DISABLE(void)
{
    __asm("CPSID   I");
    __asm("BX      LR");
}

void INTX_ENABLE(void)
{
    __asm("CPSIE   I");
    __asm("BX      LR");
}

void MSR_MSP(u32 addr) 
{
    __asm("MSR MSP, r0");
    __asm("BX r14");
}